

#include "Controller.h"
#include "Node.ih"
#include "Solver.h"
#include "parser/parser.h"
#include <set>
//#include <map>
#include <string>
#include <climits>
//#include <memory>

using namespace std;

Controller::Controller() {
    setObjectName("controller");
}

Controller::~Controller() {
}

void Controller::getSolution(Node* tree, Node* leaf) {
    // get all the expressions in the tree. If the equation has no equals signs
    // there will be one expression (8*var). If it has one equals sign there will be
    // two expressions (8*var=x) and so on.
    std::vector<Node*> v = tree->getEquals();

    // make a new solver
    Solver solver;
    unsigned int minNumVar = UINT_MAX; // hold the minimum number of variables found in the solutions
    string solutionToUse; // after next loop this will hold the solution with 
    // the least number of variables

    // for every equals we found in the tree
    for (auto it = v.begin(); it != v.end(); ++it) {
        // skip any empty nodes
        if ((*it)->toCasString().size() != 0) {
            string solution = solver.solveExact((*it)->toCasString().toAscii().data(), map<string, string>());
            set<string> s = solver.getVariables(solution);
            if (s.size() < minNumVar) {
                minNumVar = s.size();
                solutionToUse = solution;
            }
            qDebug("%s =: %s n:%i", (*it)->toCasString().toLocal8Bit().data(),
                    solution.data(), s.size());
        }
    }

    // parse the selected solution
    Q_ASSERT_X(solutionToUse.size() > 0, "", "The solution is empty.");
    //    qDebug("solution is %s",solutionToUse.data() );
    Node* n = parse(QString::fromStdString(solutionToUse));
    qDebug("using %s", n->toCasString().toAscii().data());

    // get pointer to parent node of leaf
    Node *nodeParent = qobject_cast<Node *>(leaf->parent());
    Q_ASSERT_X(nodeParent != 0, "", "nodeParent not set.");

    // replace leaf with solution
    if (leaf->isLeftChild()) {
        delete leaf;
        nodeParent->setLeftChild(n);
    } else if (leaf->isRightChild()) {
        delete leaf;
        nodeParent->setRightChild(n);
    } else if (leaf->isSingleChild()) {
        delete leaf;
        nodeParent->setSingleChild(n);
    }

    n->upDateSize();
}

Node * Controller::parse(QString input) {
    Parser parser;
    Node* n = parser.parseThis(input.toStdString());
    if (n != 0 and n != nullptr)
        return n;
    else {
        cout << "There was an error parsing: " << input.toAscii().data() << endl;
        return new NodeLeaf();
    }
}

void Controller::reparse(Node* tree, int inputPosition) {
    QString input = tree->toParseString();
    qDebug("input p is %i ",inputPosition);
    
    qDebug("Type is: %s ",tree->getNodeType().toAscii().data());
    
    Parser parser;
    Node* n = parser.parseThis(input.toStdString());
    if (n != 0 and n != nullptr) {
        delete tree->getSingleChild();
        tree->setSingleChild(n);
        tree->upDateSize();
        tree->setInputPosition(inputPosition);
    } else {
        cout << "There was an error parsing: " << input.toAscii().data() << endl;
    }
    qDebug("Resulst is: %s ",n->getNodeType().toAscii().data());
}

